/*
 *
 * Copyright (C) 2012 Walter Lütgenau
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package offset.nodes.client.veditor;

import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JToolBar.Separator;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.text.Element;
import javax.swing.text.html.HTML;
import offset.nodes.client.editor.Editor;
import offset.nodes.client.veditor.controller.DataActions;
import offset.nodes.client.veditor.controller.DataNavigationFilter;
import offset.nodes.client.editor.controller.EditorKit;
import offset.nodes.client.editor.controller.ParagraphActions;
import offset.nodes.client.editor.model.DocumentContext;
import offset.nodes.client.editor.model.EditorModel;
import offset.nodes.client.editor.model.StructureTree;
import offset.nodes.client.model.NodeTypes;
import offset.nodes.client.model.Server;
import offset.nodes.client.veditor.controller.VirtualEditorKit;
import offset.nodes.client.veditor.model.VirtualBlock;
import offset.nodes.client.veditor.controller.VirtualFileActions;
import offset.nodes.client.veditor.controller.VirtualHyperlinkActions;
import offset.nodes.client.view.component.ComponentContainer;
import offset.nodes.client.veditor.view.instance.VirtualPageInstancePanel;
import offset.nodes.client.veditor.controller.VirtualImageActions;
import offset.nodes.client.veditor.controller.VirtualViewActions;
import offset.nodes.client.veditor.model.VirtualStructureTree;
import offset.nodes.client.virtual.model.GetSchemas;
import offset.nodes.client.virtual.model.jcr.nodetype.NodeTypeDefinition;
import offset.nodes.client.virtual.model.jcr.nodetype.NodeTypeReader;

/**
 *
 * @author
 * Walter
 * Lütgenau
 */
public class VirtualEditor extends Editor {
    public static final int MODE_TEMPLATE_EDITOR = 2;
    public static final int MODE_VIRTUAL_PAGE_DATA_EDITOR = 3;
    public static final int MODE_VIRTUAL_PAGE_EDITOR = 5;
    public static final int MODE_VIRTUAL_PAGE_INSTANCE_EDITOR = 6;
    
    private VirtualPageInstancePanel virtualPageInstancePanel;    
    protected DataActions dataActions = new DataActions();    
    private javax.swing.JRadioButtonMenuItem xslViewMenuItem;
    private javax.swing.JRadioButtonMenuItem dataViewMenuItem;
    private javax.swing.JRadioButtonMenuItem virtualPageInstanceMenuItem;    
    private javax.swing.JButton deleteRowButton;
    private javax.swing.JButton backTabButton;
    private javax.swing.JButton tabButton;    
    private javax.swing.JButton saveServerButton;
    private javax.swing.JButton saveServerCommentButton;    
    
    public void initializeComponents() {
        super.initializeComponents();
        
        getBrowserSplitPane().setDividerLocation(0);
        
        xslViewMenuItem = new javax.swing.JRadioButtonMenuItem();
        dataViewMenuItem = new javax.swing.JRadioButtonMenuItem();
        virtualPageInstancePanel = new VirtualPageInstancePanel();
        virtualPageInstanceMenuItem = new javax.swing.JRadioButtonMenuItem();
        deleteRowButton = new javax.swing.JButton();
        backTabButton = new javax.swing.JButton();
        tabButton = new javax.swing.JButton();        
        saveServerButton = new javax.swing.JButton();
        saveServerCommentButton = new javax.swing.JButton();        
        
        virtualPageInstancePanel.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
        getMainPanel().add(virtualPageInstancePanel, "mapping");        
       
        xslViewMenuItem.setAction(new DataActions.XslViewAction(this));
        getMainViewButtonGroup().add(xslViewMenuItem);

        dataViewMenuItem.setAction(new DataActions.DataViewAction(this));
        getMainViewButtonGroup().add(dataViewMenuItem);

        virtualPageInstanceMenuItem.setAction(new DataActions.VirtualPageInstanceViewAction(this));
        getMainViewButtonGroup().add(virtualPageInstanceMenuItem);        
        
        getToolBar().add(new Separator(), 0);

        deleteRowButton.setAction(new DataActions.DeleteDataRowAction(this));
        deleteRowButton.setText(" ");
        deleteRowButton.setContentAreaFilled(false);
        deleteRowButton.setFocusable(false);
        deleteRowButton.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        deleteRowButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);

        getToolBar().add(deleteRowButton, 0);
        
        tabButton.setAction(new DataActions.TabAction(this));
        tabButton.setText(" ");
        tabButton.setFocusable(false);
        tabButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        getToolBar().add(tabButton, 0);     
        
        backTabButton.setAction(new DataActions.BackTabAction(this));
        backTabButton.setText(" ");
        backTabButton.setFocusable(false);
        backTabButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        getToolBar().add(backTabButton, 0);
        
        saveServerButton.setAction(new VirtualFileActions.SaveServerAction( this ));
        saveServerButton.setText(" ");

        saveServerCommentButton.setAction(new VirtualFileActions.SaveServerCommentAction( this ));
        saveServerCommentButton.setText(" ");
        
        getHyperlinkButton().setAction(new VirtualHyperlinkActions.VirtualInsertHyperlinkAction(this));
        getHyperlinkButton().setText("");
        getImageButton().setAction(new VirtualImageActions.VirtualInsertImageAction(this));        
        getImageButton().setText("");
        getTreeStructureButton().setAction(new VirtualViewActions.VirtualStructureViewAction(this));        
        getTreeStructureButton().setText("");  
        getTreeStructureMenuItem().setAction(getTreeStructureButton().getAction());
    }
    
    protected void initActions() {
        super.initActions();
        saveTemplateAs = (Action) new DataActions.SaveTemplateAsAction(this);        
    }
    
    public void setMode(int mode) throws URISyntaxException {
        boolean setCaret = true;
        switch (mode) {
            case MODE_TEMPLATE_EDITOR:
                setTemplateEditor();
                break;

            case MODE_VIRTUAL_PAGE_DATA_EDITOR:
                setVirtualPageDataEditor();
                setCaret = false;
                break;

            case MODE_VIRTUAL_PAGE_EDITOR:
                setVirtualPageEditor();
                setCaret = false;
                break;

            case MODE_VIRTUAL_PAGE_INSTANCE_EDITOR:
                break;
        }

        getBrowserPane().setEditorKit(createEditorKit());        
        EditorKit kit = (EditorKit) getBrowserPane().getEditorKit();
        kit.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK), getSaveMenuItem().getAction());

        if (setCaret) {
            EditorModel model = new EditorModel(new DocumentContext(getBrowserPane()));
            Element body = model.findNextElement(getBrowserPane().getDocument().getDefaultRootElement(), HTML.Tag.BODY.toString());
            if (body != null)
                getBrowserPane().setCaretPosition(body.getStartOffset());
        }
    }
    
    protected void setPage(URL page) throws IOException {
        getBrowserPane().setPage(page);
        fireUserCaretEvent();
    }
    
    protected StructureTree createStructureTree(JEditorPane pane, JTree tree, HashMap editorProperties, Editor editor) {
        return new VirtualStructureTree(pane, tree, editorProperties, this);
    }
    
    protected EditorKit createEditorKit() {
        return new VirtualEditorKit(this);
    }
    
    /**
     * Used to edit a virtual page, i.e. both an virtual page template node and an
     * associated virtual page instance
     */
    protected void setVirtualPageEditor() throws URISyntaxException {
        this.mode = VirtualEditor.MODE_VIRTUAL_PAGE_EDITOR;
        
        getTreeStructureMenuItem().doClick();
        getStructure().addNodePopups(ParagraphActions.getParagraphStructurePopups(this));
        
        // change actions
        getSaveMenuItem().setAction(new DataActions.SaveVirtualPageAction(this)); // TODO
        getSaveServerButton().setAction(getSaveMenuItem().getAction());
        getSaveServerButton().setText("");        
        getExitMenuItem().setAction(new DataActions.ExitVirtualPageAction(this));
        getExitButton().setAction(getExitMenuItem().getAction());
        getExitButton().setText(" ");

        // for now, remove save comment action - not implemented yet for virtual page editor
        getFileMenu().remove(getSaveCommentMenuItem());
        getToolBar().remove(getSaveServerCommentButton());
        getFileMenu().remove(getSaveCommentMenuItem());
        getToolBar().remove(getSaveServerCommentButton());
        
        getFileMenu().addSeparator();
        getFileMenu().add(getAddStyleSheetMenuItem()); // only for templates to prevent diverging use of stylesheets in normal editing
        getViewMenu().addSeparator();
        getViewMenu().add(getXslViewMenuItem()); // TODO: move
        getViewMenu().add(getVirtualPageInstanceMenuItem());
        getTabButton().setVisible(false);
        getBackTabButton().setVisible(false);
    }

    /**
     * Used to edit a tree node template
     */
    protected void setTemplateEditor() throws URISyntaxException {
        this.mode = VirtualEditor.MODE_TEMPLATE_EDITOR;
        
        getTreeStructureMenuItem().doClick();
        getStructure().addNodePopups(ParagraphActions.getParagraphStructurePopups(this));
        
        getSaveMenuItem().setAction(new DataActions.SaveTemplatePageAction(this));
        getSaveServerButton().setAction(getSaveMenuItem().getAction());
        getSaveServerButton().setText("");
        
        getFileMenu().remove(getSaveCommentMenuItem());
        getToolBar().remove(getSaveServerCommentButton());
        getExitMenuItem().setAction(new DataActions.ExitTemplatePageAction(this));
        getExitButton().setAction(getExitMenuItem().getAction());
        getExitButton().setText(" ");
        getFileMenu().addSeparator();
        getFileMenu().add(getAddStyleSheetMenuItem()); // only for templates to prevent diverging use of stylesheets in normal editing
        getViewMenu().add(getXslViewMenuItem());
        getTabButton().setVisible(false);
        getBackTabButton().setVisible(false);
    }

    /**
     * Edit a virtual page. Extract data on save.
     */
    protected void setVirtualPageDataEditor() throws URISyntaxException {
        this.mode = VirtualEditor.MODE_VIRTUAL_PAGE_DATA_EDITOR;
        
        getBrowserPane().setNavigationFilter(new DataNavigationFilter(this));
        getTreeStructureMenuItem().doClick();    
        
        // change actions
        getSaveMenuItem().setAction(new DataActions.SaveDataAction(this));
        getSaveCommentMenuItem().setAction(new DataActions.SaveDataCommentAction(this));
        getSaveServerButton().setAction(getSaveMenuItem().getAction());
        getSaveServerButton().setText(" ");
        getSaveServerCommentButton().setAction(getSaveCommentMenuItem().getAction());
        getSaveServerCommentButton().setText(" ");
        
        dataActions.setCaretSetAction(new DataActions.SetCaretAction(this));
        addUserCaretListener(dataActions.getCaretSetAction());

        getNumberedListButton().setVisible(false);
        getBulletListButton().setVisible(false);
        getIndentLeftButton().setVisible(false);
        getIndentRightButton().setVisible(false);
        getjSeparator1().setVisible(false);
        getjSeparator2().setVisible(false);
        getjSeparator3().setVisible(false);
        getHeading1Button().setVisible(false);
        getHeading2Button().setVisible(false);
        getCodeButton().setVisible(false);
        getjSeparator4().setVisible(false);
        getBoldButton().setVisible(false);
        getItalicButton().setVisible(false);
        getUnderlineButton().setVisible(false);
        getCodeSpanButton().setVisible(false);
        getjSeparator5().setVisible(false);
        getHyperlinkButton().setVisible(false);
        getImageButton().setVisible(false);
        getjSeparator6().setVisible(false);
        getTreeHeadingButton().setVisible(false);
        getTreeStructureButton().setVisible(false);

        getInsertMenu().setVisible(false);
        getTableMenu().setVisible(false);

        getViewMenu().add(getDataViewMenuItem());
    }

    public void destroy() {
        VirtualBlock.destroy((String) properties.get(PROP_DOCUMENT_PATH));
    }
    
    protected NodeTypes getNodeTypes(Server server) {
        GetSchemas.Request request = new GetSchemas.Request();
        GetSchemas.Response response = null;
        try {
            response = (GetSchemas.Response) server.sendRequest(request);
            InputStream in = new ByteArrayInputStream(response.getSchemaXml().getBytes());
            NodeTypeDefinition[] definitions = NodeTypeReader.read(in);
            return new NodeTypes(definitions);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }    
    
    public ComponentContainer getComponentContainer() {
        return componentContainer;
    }

    public void setComponentContainer(ComponentContainer componentContainer) {
        this.componentContainer = componentContainer;
    }

    public VirtualPageInstancePanel getVirtualPageInstancePanel() {
        return virtualPageInstancePanel;
    }    
    
    public DataActions getDataActions() {
        return dataActions;
    }    

    public JRadioButtonMenuItem getXslViewMenuItem() {
        return xslViewMenuItem;
    }

    public JRadioButtonMenuItem getDataViewMenuItem() {
        return dataViewMenuItem;
    }

    public JRadioButtonMenuItem getVirtualPageInstanceMenuItem() {
        return virtualPageInstanceMenuItem;
    }

    public JButton getDeleteRowButton() {
        return deleteRowButton;
    }

    public JButton getBackTabButton() {
        return backTabButton;
    }

    public JButton getTabButton() {
        return tabButton;
    }

}
